package com.sann.util;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 用于记录日志的工具类，它里面提供了公共的代码
 * 在Spring注解版AOP中，推荐使用环绕通知，如果把前置、后置、异常、最终通知分开，会发现通知输出的顺序有点问题。
 */
@Slf4j
@Component(value = "logger")
@Aspect//表明当前类是一个切面类
public class Logger {

    // 注册切入点
    @Pointcut("execution(* com.sann.service.impl..*.*(..))")
    public void pc1(){

    };

    /**
     * 注册前置通知,绑定切入点pc1
     */
    //@Before("pc1()")
    public void beforePrintLog(){
        log.info("前置通知...");
    }

    /**
     * 注册后置通知,绑定切入点pc1
     */
    //@AfterReturning("pc1()")
    public void afterReturningPrintLog(){
        log.info("后置通知...");
    }

    /**
     * 注册异常通知,绑定切入点pc1
     */
    //@AfterThrowing("pc1()")
    public void afterThrowingPrintLog(){
        log.info("异常通知...");
    }

    /**
     * 最终通知,绑定切入点pc1
     */
    //@After("pc1()")
    public void afterPrintLog(){
        log.info("最终通知...");
    }

    /**
     * 环绕通知,绑定切入点pc1
     */
    @Around("pc1()")
    public Object aroundPrintLog(ProceedingJoinPoint pjp){
        Object rtValue = null;
        try {
            Object[] args = pjp.getArgs();
            log.info("环绕通知：前置通知...");
            rtValue = pjp.proceed(args);
            log.info("环绕通知：后置通知...");
            return rtValue;
        }catch (Throwable t){
            log.info("环绕通知：异常通知...");
            throw new RuntimeException(t);
        }finally {
            log.info("环绕通知：最终通知...");
        }
    }

}























